#pragma once
#include<unistd.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include "inetaddress.h"
#include "util.h"

inline
int bind_wrap(int fd, sockaddr* addr, socklen_t len) {
    int res = bind(fd, addr, len);
    errif(res==-1, "socket bind error");
    return res;
}

inline
int listen_wrap(int fd, int n) {
    int res = listen(fd, n);
    errif(res==-1, "socket bind error");
    return res;
}

inline
int accept_wrap(int fd, sockaddr* addr, socklen_t len) {
    int clnt_sockfd = accept(fd, (sockaddr*)&addr, &len);
    errif(clnt_sockfd==-1, "socket bind error");
    return clnt_sockfd;
}

class Socket
{
private:
    /* data */
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
public:
    Socket(/* args */);
    Socket(int fd):sockfd(fd){};
    ~Socket();
    int bind(std::shared_ptr<InetAddress>);
    int listen();
    int accept(std::unique_ptr<InetAddress>);
    int getFd() {
        return sockfd;
    }
};

Socket::Socket(/* args */)
{
}

Socket::~Socket()
{
}

int Socket::bind(std::shared_ptr<InetAddress> inet_addr) {
    return bind_wrap(sockfd, (sockaddr*)&inet_addr->serv_addr(), 
        sizeof(inet_addr->serv_addr()));
}


int Socket::listen() {
    return listen_wrap(sockfd, SOMAXCONN);
}

int Socket::accept(std::unique_ptr<InetAddress> inet_addr) {
    return accept_wrap(sockfd, (sockaddr*)&inet_addr->serv_addr(), sizeof(inet_addr->serv_addr()));
}
